package thread;

/**
 * 线程同步机制-Synchronized关键字
 *
 * synchronized(对象) {//得到对象的锁，才能操作同步代码
 *     //需要被同步的代码;
 * }
 *
 * public synchronized void m (String name){
 *     //需要被同步的代码
 * }
 */
public class Synchronized_ {

    public static void main(String[] args) {

        /*
            1)在多线程编程中，一些敏感数据不允许被多个线程同时访问，此时就使用同步访问技术
              保证数据在任何同一时刻，最多有一个线程访问，以保证数据的完整性

            2)也可以这样理解：线程同步，即当有一个线程在堆内存进行操作时，其他线程都不可以对这个内存地址进行操作
              直到该线程完成操作，其他线程才能对该内存地址进行操作

            例：使用synchronized解决售票的超卖问题
         */

        /*
            3个售票窗口售出100张
         */

        SellTicket02 sellTicket = new SellTicket02();

        //启动3个售票线程
        new Thread(sellTicket).start();
        new Thread(sellTicket).start();
        new Thread(sellTicket).start();
    }
}

//使用Thread方式，使用synchronized 实现线程同步
class SellTicket02 implements Runnable {

    private static int num = 100;   //让多个线程共享 num

    private boolean loop = true;

    public synchronized void sell() { //同步方法，在同一个时刻，只能有一个线程来执行sell方法

        if (num == 0) {
            System.out.println("售票结束...");
            loop = false;
            return;
        }

        System.out.println("窗口 " + Thread.currentThread().getName() + "售出1张票" + "剩余票数=" + (--num));
    }

    @Override
    public void run() {
        while (loop) {
            sell(); //sell方法是一个同步方法
            //休眠50ms，模拟人休息
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}